/**
 * @file SVG转图片工具
 * @description 在渲染进程中将@mdi/js的SVG路径转换为PNG图片数据，用于Electron原生菜单图标
 * @features
 * - SVG到PNG转换
 * - 智能缓存机制
 * - 批量转换支持
 * - 缓存预热功能
 * @author 黄敏
 * @version 2.0.0
 * @since 2025-07-03
 */

/**
 * 计算字符串的短哈希（FNV-1a 32位）
 * 说明：返回十六进制字符串，碰撞概率极低，适合作为缓存键
 */
function hashStringFNV1a(input: string): string {
  let hash = 0x81_1c_9d_c5
  for (let i = 0; i < input.length; i++) {
    hash ^= input.charCodeAt(i)
    // 乘以 16777619，使用位运算避免浮点乘法
    hash = (hash + ((hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24))) >>> 0
  }
  return hash.toString(16)
}

/**
 * 将SVG路径转换为PNG图片的base64数据
 * @param svgPath - SVG路径字符串（来自@mdi/js）
 * @param size - 图标大小，默认16x16
 * @param color - 图标颜色，默认深灰色
 * @returns Promise<string | null> - PNG图片的base64 data URL
 */
export async function svgPathToImageData(
  svgPath: string,
  size = 16,
  color = '#333333'
): Promise<string | null> {
  try {
    // 创建SVG字符串
    const svgString = `<svg width="${size}" height="${size}" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
      <path d="${svgPath}" fill="${color}"/>
    </svg>`

    // 创建Canvas元素
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')

    if (!ctx) {
      return null
    }

    // 设置canvas尺寸
    canvas.width = size
    canvas.height = size

    // 创建SVG的data URL
    const svgDataUrl = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgString)}`

    return new Promise(resolve => {
      const img = new Image()

      img.addEventListener('load', () => {
        try {
          // 清除canvas并绘制图像
          ctx.clearRect(0, 0, size, size)
          ctx.drawImage(img, 0, 0, size, size)

          // 转换为PNG的base64数据
          const pngDataUrl = canvas.toDataURL('image/png')
          resolve(pngDataUrl)
        } catch {
          resolve(null)
        }
      })

      img.onerror = () => resolve(null)

      // 设置超时
      setTimeout(() => resolve(null), 1000)

      // 开始加载SVG
      img.src = svgDataUrl
    })
  } catch {
    return null
  }
}

/**
 * 批量转换多个SVG路径为图片数据
 * @param svgPaths - SVG路径数组
 * @param size - 图标大小
 * @param color - 图标颜色
 * @returns Promise<Record<string, string | null>> - 路径到图片数据的映射
 */
export async function batchConvertSvgPaths(
  svgPaths: string[],
  size = 16,
  color = '#333333'
): Promise<Record<string, string | null>> {
  const results: Record<string, string | null> = {}

  // 并行转换所有SVG，使用缓存版本
  const promises = svgPaths.map(async svgPath => {
    const imageData = await svgPathToImageDataCached(svgPath, size, color)
    results[svgPath] = imageData
  })

  await Promise.all(promises)
  return results
}

/**
 * 图标缓存管理器
 */
class IconCache {
  private cache = new Map<string, string | null>()
  private maxSize = 100 // 最大缓存数量

  /**
   * 生成缓存键
   */
  private generateKey(svgPath: string, size: number, color: string): string {
    // 使用 FNV-1a 对 svgPath 做短哈希，既避免键过长，又避免不同图标前缀相同导致的碰撞
    const hash = hashStringFNV1a(svgPath)
    return `${hash}-${size}-${color}`
  }

  /**
   * 获取缓存的图标数据
   */
  get(svgPath: string, size: number, color: string): string | null | undefined {
    const key = this.generateKey(svgPath, size, color)
    return this.cache.get(key)
  }

  /**
   * 设置缓存的图标数据
   */
  set(svgPath: string, size: number, color: string, imageData: string | null): void {
    const key = this.generateKey(svgPath, size, color)

    // 如果缓存已满，删除最旧的条目
    if (this.cache.size >= this.maxSize) {
      const firstKey = this.cache.keys().next().value
      if (firstKey) {
        this.cache.delete(firstKey)
      }
    }

    this.cache.set(key, imageData)
  }

  /**
   * 清除缓存
   */
  clear(): void {
    this.cache.clear()
  }

  /**
   * 获取缓存统计信息
   */
  getStats(): { size: number; maxSize: number; hitRate?: number } {
    return {
      size: this.cache.size,
      maxSize: this.maxSize
    }
  }
}

// 导出单例缓存实例
export const iconCache = new IconCache()

/**
 * 带缓存的SVG转换函数
 * @param svgPath - SVG路径字符串
 * @param size - 图标大小
 * @param color - 图标颜色
 * @returns Promise<string | null> - PNG图片的base64 data URL
 */
export async function svgPathToImageDataCached(
  svgPath: string,
  size = 16,
  color = '#333333'
): Promise<string | null> {
  // 检查缓存
  const cached = iconCache.get(svgPath, size, color)
  if (cached !== undefined) {
    return cached
  }

  // 转换并缓存
  const imageData = await svgPathToImageData(svgPath, size, color)
  iconCache.set(svgPath, size, color, imageData)

  return imageData
}

/**
 * 获取缓存统计信息
 */
export function getCacheStats() {
  return iconCache.getStats()
}

/**
 * 清除图标缓存
 */
export function clearIconCache() {
  iconCache.clear()
}

/**
 * 预热常用图标缓存
 * @param commonIcons - 常用图标的SVG路径数组
 */
export async function preloadCommonIcons(commonIcons: string[]) {
  try {
    await batchConvertSvgPaths(commonIcons)
  } catch (error) {
    console.warn('预热图标缓存失败:', error)
  }
}
